/****************************************************************************
 * exu.v
 ****************************************************************************/
`include "defines.v"

/****************************************************************************
   Module: exu
  
   所有信号遵从正逻辑，即信号电平为1的含义与信号变量名称的含义一致，如rst信号
   为1代表复位，0代表复位信号无效，系统正常工作
   
   执行单元接收ifu和dec模块传递过来的信号，按照指令的信息调用对应的单元执行。
   执行完成后根据指令情况，会生成以下四种结果信息：
    a. 寄存器写入值，写入使能信号，写入寄存器的idx
    b. csr寄存器写入值，写入使能信号，掩码（仅对于掩码对应的bit位写入，csr支持按位读写）
    c. 控制信号：HLT指令的done信号；跳转指令的taken信号，及跳转目的地址；阻塞取指的ifu2exu_cmd_ack信号
    d. 内存写入值，内存的地址，写使能；内存读取地址，读使能

   不同的单元会输出以上四种信号的一种或者几种：
    1. rglr - a & b
    2. lsu  - a & d
    3. bjp  - a & c
    4. csr  - a & b
    5. long - a & c
    6. ctrl - a & c
 ****************************************************************************/

module exu
(
    // 上层系统向deu发送启动工作的信号接口，icb标准信号，exu为从设备接收命令
    input                           sys2exu_cmd_start,      // 系统工作启动信号，单周期脉冲，高电平有效
    input                           sys2exu_cmd_req,
    output                          sys2exu_cmd_ack,

    // // 数据存储器相关接口，采用icb标准信号接口，exu作为主设备读写mem
    // output                          exu2mem_cmd_wr,         // 写读命令，高电平写，低电平读
    // output                          exu2mem_cmd_req,      
    // input                           exu2mem_cmd_ack,      
    // input                           exu2mem_rsp_req,
    // output                          exu2mem_rsp_ack,
    // input                           exu2mem_rsp_err,
    // output [`DATA_ADDR_WIDTH-1 : 0] exu2mem_addr,           // 地址
    // output [`DATA_WIDTH-1 : 0]      exu2mem_dout,           // 写数据
    // input  [`DATA_WIDTH-1 : 0]      exu2mem_din,            // 读数据

    // // 前端取指单元相关接口，此时exu模块作为从设备接收ifu单元发送的信号和数据
    // input                           ifu2exu_cmd_req,        // ifu发送给后端译码和执行单元deu的命令请求状态信号，高电平有效
    // output                          ifu2exu_cmd_ack,        // 后端译码执行单元deu反馈的命令接受状态信号，高电平有效
    // output                          ifu2exu_rsp_req,        // 后端deu译码执行单元反馈的请求信号
    // input                           ifu2exu_rsp_ack,        // ifu发送给后端deu的反馈请求接受状态信号
    // output                          ifu2exu_rsp_done,       // deu向ifu发送的程序执行完毕信号，HLT指令执行完
    // output                          ifu2exu_rsp_taken,      // deu根据执行结果反馈给ifu的跳转指令结果，1-跳转，0-不跳转

    // ifu相关接口，此时取指模块作为主设备向译码执行单元写数据
    input                           ifu2exu_cmd_req,        // 发送给后端译码和执行单元的命令状态信号，高电平有效
    output                          ifu2exu_cmd_ack,        // 后端译码执行单元反馈的命令接受状态信号，高电平有效
    output                          ifu2exu_rsp_req,        // 后端执行单元exu反馈的请求信号
    input                           ifu2exu_rsp_ack,        // ifu发送给后端exu的请求接受状态信号
    output                          ifu2exu_rsp_done,       // exu向ifu发送的程序执行完毕信号，HLT指令执行完
    output                          ifu2exu_rsp_taken,      // exu根据执行结果反馈给ifu的跳转指令执行结果，1-跳转
    output                          ifu2exu_rsp_mem_addr,   // exu根据执行结果反馈给ifu的跳转目的地址

    // ifu和dec模块的接口信号，因为dec模块为纯组合逻辑，不涉及时序控制，因此无请求和响应交互信号
    input                           ifu2dec_instr_jmp,      // 无条件跳转指令
    input                           ifu2dec_instr_bjp,      // 条件跳转指令
    input [`CODE_WIDTH-1 : 0]       ifu2dec_instr,          // 指令
    input [`CODE_ADDR_WIDTH-1 : 0]  ifu2dec_pc,             // 当前指令的pc值

    // 寄存器regfile模块和csr模块信号
    output  [`REG_ID_WIDTH-1 : 0]    rf_rd_src1_idx,
    output  [`REG_ID_WIDTH-1 : 0]    rf_rd_src2_idx,
    input   [`REG_WIDTH*2-1 : 0]     rf_rd_src1_dat,
    input   [`REG_WIDTH*2-1 : 0]     rf_rd_src2_dat,
    input   [`REG_WIDTH-1 : 0]       csr_rd_dat,

    //系统复位和时钟信号
    input                           rst,                    // 系统复位信号，同步复位，高电平有效
    input                           clk                     // 系统工作时钟
);


    //-------------------------------------------------------------------------------
    // 实例化decode模块

    wire                                dec2exu_rglr;
    wire                                dec2exu_lsu;
    wire                                dec2exu_bjp;
    wire                                dec2exu_csr;
    wire                                dec2exu_long;
    wire                                dec2exu_ctrl;

    wire                                dec2exu_regfile_rd1_en;
    wire                                dec2exu_regfile_rd2_en;
    wire [`REG_ID_WIDTH-1 : 0]          dec2exu_regfile_rd1_idx;
    wire [`REG_ID_WIDTH-1 : 0]          dec2exu_regfile_rd2_idx;

    wire                                dec2exu_need_imm;
    wire [`CODE_WIDTH-1 : 0]            dec2exu_imm_b16;
    wire [`INSTR_INFO_BUS_WIDTH-1 : 0]  dec2exu_instr_info;

    decode decode_inst(
        // 前端取指单元ifu相关接口，dec模块为纯组合逻辑，因为与前后端均无req、ack等握手信号
        .ifu2dec_instr_jmp(ifu2dec_instr_jmp),      // 无条件跳转指令
        .ifu2dec_instr_bjp(ifu2dec_instr_bjp),      // 条件跳转指令
        .ifu2dec_instr(ifu2dec_instr),              // 指令除了op1剩余的部分
        .ifu2dec_pc(ifu2dec_pc)                     // 当前指令的pc值

        // 译码单元与后端执行单元exu的接口信号
        .dec2exu_rglr(dec2exu_rglr),                // 普通运算指令单元
        .dec2exu_lsu(dec2exu_lsu),                  // 访存指令单元
        .dec2exu_bjp(dec2exu_bjp),                  // 分支预测指令单元
        .dec2exu_csr(dec2exu_csr),                  // CSR读写指令单元
        .dec2exu_long(dec2exu_long),                // 长周期运算指令单元
        .dec2exu_ctrl(dec2exu_ctrl),                // 控制类指令单元

        .dec2exu_regfile_rd1_en(dec2exu_regfile_rd1_en),   // 寄存器文件读端口1读使能
        .dec2exu_regfile_rd2_en(dec2exu_regfile_rd2_en),   // 寄存器文件读端口2读使能
        .dec2exu_regfile_rd1_idx(dec2exu_regfile_rd1_idx), // 寄存器文件读端口1的idx
        .dec2exu_regfile_rd2_idx(dec2exu_regfile_rd2_idx), // 寄存器文件读端口2的idx

        .dec2exu_need_imm(dec2exu_need_imm),               // 需要立即数参与执行
        .dec2exu_imm_b16(dec2exu_imm_b16),                 /* 16位立即数，部分单元需要将指令扩展为32位，
                                                                由对应的单元自行扩展，译码模块不做处理 */

        .dec2exu_instr_info(dec2exu_instr_info)            // 解析出来的具体的指令信息
    );

    // 生成寄存器文件读信号
    assign rf_rd_src1_idx = {`REG_ID_WIDTH{dec2exu_regfile_rd1_en}} & dec2exu_regfile_rd1_idx;
    assign rf_rd_src2_idx = {`REG_ID_WIDTH{dec2exu_regfile_rd2_en}} & dec2exu_regfile_rd2_idx;

    
    //-------------------------------------------------------------------------------
    // 实例化datapath模块

    wire [`REG_WIDTH*2-1 : 0] op1;
    wire [`REG_WIDTH*2-1 : 0] op2;
    wire [[`REG_WIDTH-1 : 0]] csr_in;
    wire [`REG_WIDTH-1 : 0]   pc;
    datapath datapath_inst(
        .rst(rst),               // 系统复位信号，同步复位，高电平有效
        .clk(clk),               // 系统工作时钟

        .op1(),               // 计算操作数1，经过合并处理的结果，imm/reg
        .op2(),               // 计算操作数2，经过合并处理的结果，imm/reg
        .csr_in(),            // csr寄存器当前的值
        .pc(),                // 当前指令的pc值

        .rglr_en(dec2exu_rglr),           // 普通运算指令单元
        .bjp_en(dec2exu_bjp),            // 分支跳转指令单元
        .csr_en(dec2exu_csr),            // CSR读写指令单元
        .ctrl_en(dec2exu_ctrl),           // 控制类指令单元
        .instr_info(dec2exu_instr_info),        // 解析出来的具体的指令信息

        .csr_out(),           // csr寄存器结果输出值
        .reg_data(),          // 寄存器结果
        .done(),              // HLT指令置位done信号，代表程序执行完毕，CPU状态复位
        .taken(),             // 跳转执行结果，
        .bjp_dest_addr(),     // 跳转目的地址
        .ifu_block()          // 阻塞取指信号
    );


endmodule
